var gamejs = require('gamejs');
var AntColonyProvider = require('js/antColonyProvider').AntColonyProvider;

/**
 * Creates a map, which holds a matrix of the navigable terrain and the obstacles
 * @param {Match} match the current match
 * @param {number} width the map width
 * @param {number} height the map height
 */
var Map = exports.Map = function(match, width, height) {

	// Using typed arrays is extremely faster, and using integers rather than booleans is much faster too
	this.matrix = new Int8Array(width * height);

	// 1D array, then we pick the points with (x + y * width)
	for (var i = 0; i < this.matrix.length; i++) {
		this.matrix[i] = 0;
	}

	this.obstacles = new gamejs.sprite.Group();
	this.enemies = new gamejs.sprite.Group();
	this.turrets = new gamejs.sprite.Group();
	this.radars = new gamejs.sprite.Group();
	this.explosions = new gamejs.sprite.Group();

	this.SIZE = [width, height];
	this.currentMatch = match;
	this.background = gamejs.image.load(config.dir.images + "background.png");
};

/**
 * Return the match where this map work.
 *
 * @return {Match} The match where this map work.
 */
Map.prototype.getMatch = function() {
	return this.currentMatch;
};

/**
 * Return the explosions gruop.
 *
 * @return {Group} The explosions group.
 */
Map.prototype.getExplosion = function() {
	return this.explosions;
};

/**
 * Return the enemies group.
 *
 * @return {Group} The enemies group.
 */
Map.prototype.getEnemies = function() {
	return this.enemies;
};

/**
 * Return the obstaclesgroup.
 *
 * @return {Group} The obstacles group.
 */
Map.prototype.getObstacles = function() {
	return this.obstacles;
};

/**
 * Return the turrets group.
 *
 * @return {Group} The turrets group.
 */
Map.prototype.getTurrets = function() {
	return this.turrets;
};

/**
 * Return the radars group.
 *
 * @return {Group} The radars group.
 */
Map.prototype.getRadars = function() {
	return this.radars;
};

/**
 * Update function
 */
Map.prototype.update = function(msDuration){
	//update stuff here
	this.radars.update(msDuration);
	this.enemies.update(msDuration);
	this.turrets.update(msDuration);
	this.explosions.update(msDuration);
	AntColonyProvider.get().update(msDuration);
};

/**
 * Draw on surface

 * @param {gamejs.surface} where to draw
 */
Map.prototype.draw = function(surface){
	surface.blit(this.background);
	this.currentMatch.draw(surface);
	this.radars.draw(surface);
	this.obstacles.draw(surface);
	this.enemies.draw(surface);
	this.turrets.draw(surface);
	this.explosions.draw(surface);
};

/**
 * Get the current map size
 *
 * @returns {Number[]}  The width and height of the Surface
 */
Map.prototype.getSize = function(){
	return this.SIZE;
};

/**
 * Fill a pixel
 *
 * @param {array} coordinates The coordinates as vector [x, y]
 */
Map.prototype.fill = function(coordinates) {
	// x + y * width
	this.matrix[coordinates[0] + coordinates[1] * this.SIZE[0]] = 1;
};

/**
 * Clear a pixel
 *
 * @param {array} coordinates The coordinates as vector [x, y]
 */
Map.prototype.clear = function(coordinates) {
	// x + y * width
	this.matrix[coordinates[0] + coordinates[1] * this.SIZE[0]] = 0;
};

/**
 * Tells if the pixel is filled
 *
 * @param {array} coordinates The coordinates as vector [x, y]
 *
 * @returns {boolean} True if the pixel is filled, false otherwise
 */
Map.prototype.isFilled = function(coordinates) {
	// x + y * width
	if((coordinates[0] < this.SIZE[0])&& (coordinates[0] >= 0) && (coordinates[1] < this.SIZE[1]) && (coordinates[1] >= 0))
		return this.matrix[coordinates[0] + coordinates[1] * this.SIZE[0]] === 1;
	return true;
};

/**
 * Adds an obstacle to the map and fills the sprite area
 *
 * @param {Obstacle} obstacle The obstacle to add
 */
Map.prototype.addObstacle = function(obstacle) {
	this.obstacles.add(obstacle);

	for(var i = obstacle.getCenter()[0] - obstacle.getRadius();
		i < obstacle.getCenter()[0] + obstacle.getRadius(); i++)
	{
		for(var j = obstacle.getCenter()[1] - obstacle.getRadius();
			j < obstacle.getCenter()[1] + obstacle.getRadius(); j++)
		{
			// -4 to count the current aura of the obstacle
			var x = Math.abs(i - 4 - obstacle.getCenter()[0]);
			var y = Math.abs(j - 4 - obstacle.getCenter()[1]);
			if (Math.sqrt(x * x + y * y) < obstacle.getRadius())
			{
				this.fill([i, j]);
			}
		}
	}
};

/**
 * Removes an obstacle to the map and clears the sprite area
 *
 * @param {Obstacle} obstacle The obstacle to remove
 */
Map.prototype.removeObstacle = function(obstacle) { };

/**
 * Adds an enemy to the map and fills the sprite area
 *
 * @param {Enemy} enemy The enemy to add
 */
Map.prototype.addEnemy = function(enemy) {
	this.enemies.add(enemy);
};

/**
 * Adds an enemy to the map and fills the sprite area
 *
 * @param {Enemy} enemy The enemy to add
 */
Map.prototype.addExplosion = function(explosion) {
	this.explosions.add(explosion);
};

/**
 * Removes enemy to the map and clears the sprite area
 *
 * @param {Enemy} enemy  They enemy to remove
 */
Map.prototype.removeEnemy = function(enemy) { };

/**
 * Adds turrett the map and fills the sprite area
 *
 * @param {Turret} turret The turret to add
 */
Map.prototype.addTurret = function(turret) {
	this.turrets.add(turret);
};

/**
 * Removes an turret from the map and clears the sprite area
 *
 * @param {Turret} turret The turret to remove
 */
Map.prototype.removeTurret = function(turret){ };

/**
 * Adds a radar to the map and fills the sprite area
 *
 * @param {Radar} radar The radar to add
 */
Map.prototype.addRadar = function(radar) {
	this.radars.add(radar);
};

/**
 * Removes a radar to the map and clears the sprite area
 *
 * @param {Radar} radar The radar to remove
 */
Map.prototype.removeRadar = function(radar) { };